/*
 * PDFHandler.java
 *
 * Created on 2 September 2006, 1:16
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package fasea.index.filehandler;

import fasea.ui.utils.ImageControl;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.pdfbox.cos.COSDocument;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.encryption.DecryptionMaterial;
import org.apache.pdfbox.pdmodel.encryption.SecurityHandler;
import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
import org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler;
import org.apache.pdfbox.util.PDFTextStripper;
import org.jpedal.PdfDecoder;

/**
 *
 * @author gvasil
 * @author lars-wolfram
 */
class PDFHandler extends FileHandler {

    public static String password = "-password";

    public Document getTypedDocument(File file) throws FileHandlerException {
        InputStream is = null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            throw new FileHandlerException(
                    "File not found: "
                    + file.getAbsolutePath(), e);
        }

        org.apache.lucene.document.Document doc = createDefaultLuceneDocument(file);

        PDDocument pdDocument = null;
        COSDocument cosDoc = null;
        try {
            cosDoc = parseDocument(is);
            pdDocument = new PDDocument(cosDoc);

            // decrypt the PDF document, if it is encrypted

            if (cosDoc.isEncrypted()) {
                SecurityHandler securityHandler = new StandardSecurityHandler();
                DecryptionMaterial material = new StandardDecryptionMaterial(password);
                securityHandler.decryptDocument(pdDocument, material);
            }

            byte[] bytes = null;
            try {
                PdfDecoder decoder = new PdfDecoder(true);
                decoder.openPdfFile(file.getAbsolutePath());
                if (decoder.getPageCount() > 0) {
                    decoder.setPageParameters(1f, 1);
                    decoder.setExtractionMode(0); 
                    ImageControl imgctl = ImageControl.getImageControl();
                    BufferedImage img = imgctl.getScaledCover(decoder.getPageAsImage(1));
                    decoder.closePdfFile();
                    bytes = imgctl.toByteArray(img);
                    decoder = null;
                }
            } catch (Exception ex) {
                Logger.getLogger(PDFHandler.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (bytes != null) {
                doc.add(new Field("thumbnail", bytes));
            }

            // extract PDF document's textual content
            PDFTextStripper stripper = new PDFTextStripper();
            String text = stripper.getText(pdDocument);

            doc.add(new Field("content", text, Field.Store.NO,
                    Field.Index.ANALYZED, Field.TermVector.WITH_OFFSETS));

            // extract PDF document's meta-data
            PDDocumentInformation docInfo = pdDocument.getDocumentInformation();
            String author = docInfo.getAuthor();
            String title = docInfo.getTitle();
            String keywords = docInfo.getKeywords();
            String summary = docInfo.getSubject();
            if ((author != null) && (!author.equals(""))) {
                doc.add(new Field("author", author, Field.Store.YES, Field.Index.NO));
            }
            if ((title != null) && (!title.equals(""))) {
                doc.add(new Field("title", title, Field.Store.YES, Field.Index.NO));
            }
            if ((keywords != null) && (!keywords.equals(""))) {
                doc.add(new Field("keywords", keywords, Field.Store.YES, Field.Index.NO));
            }
            if ((summary != null) && (!summary.equals(""))) {
                doc.add(new Field("summary", summary, Field.Store.YES, Field.Index.NO));
            }
        } catch (Exception e) {
            //throw new DocumentHandlerException("Cannot parse PDF document", e);
            return doc;
        } finally {
            closeCOSDocument(cosDoc);
            closePDDocument(pdDocument);
        }
        return doc;
    }

    private static COSDocument parseDocument(InputStream is) throws IOException {
        PDFParser parser = new PDFParser(is);
        parser.parse();
        return parser.getDocument();
    }

    private void closeCOSDocument(COSDocument cosDoc) {
        if (cosDoc != null) {
            try {
                cosDoc.close();
            } catch (IOException e) {
                // eat it, what else can we do?
            }
        }
    }

    private void closePDDocument(PDDocument pdDoc) {
        if (pdDoc != null) {
            try {
                pdDoc.close();
            } catch (IOException e) {
                // eat it, what else can we do?
            }
        }
    }
}